/*
 * chrome://tabmixplus/content/session/sessionStore.js
 *
 * original code by onemen
 *
 */

/*
XUL Tab attributes to (re)store
Restored in nsSessionStore restoreHistory()
*/
const _xulAttributes = ["image", "protected", "_locked", "fixed-label", "label-uri", "reload-data"];

var TMP_SessionStore = {
   /**
    * @brief       - Init nsISessionStore if user enable browser.sessionstore.enabled from about:config
    *                or from Tabmix Options > session.
    *              - Add attribute to nsSessionStore persistTabAttribute.
    *
    * @param doInit   a Boolean value - true when we need to init nsISessionStore.
    *
    * @returns        Nothing.
    */
   init: function TMP_ss_init(doInit) {
      var ss = Cc["@mozilla.org/browser/sessionstore;1"].
                  getService(Ci.nsISessionStore);
      if(doInit) {
         try {
            ss.init(window);
         } catch(ex) {
            dump("nsSessionStore could not be initialized: " + ex + "\n");
            return;
         }
      }

      try {
         _xulAttributes.forEach(function(aAttr) {
            ss.persistTabAttribute(aAttr);
         });
      } catch(ex) {
         dump("nsSessionStore could not add Attribute to persistTabAttribute: " + ex + "\n");
      }
   },

   /**
    * @brief         make sure that we don't enable both sessionStore and session manager
    *
    * @param msgNo   a Integer value - msg no. to show.
    *
    * @param start   a Boolean value - true if we call this function befor startup.
    *
    * @returns       Nothing.
    */
   setService: function TMP_ss_setSessionService(msgNo, start, win) {
      if (!gIsFirefox2)
         return;

      if(window.setSession || gPref.prefHasUserValue("extensions.tabmix.setDefault"))
         return;

      window.setSession = true;

      var sessionStore = TMP_getBoolPref("", "browser.sessionstore.enabled", true);
      var sessionManager = gPref.getBoolPref("extensions.tabmix.sessions.manager");
      var crashRecovery = gPref.getBoolPref("extensions.tabmix.sessions.crashRecovery");

      if (sessionStore && (sessionManager || crashRecovery)) {
         var promptService = Cc["@mozilla.org/embedcomp/prompt-service;1"]
                                 .getService(Ci.nsIPromptService);
         var bundle_session = document.getElementById("bundle_session_manager");

         var msg = start ? bundle_session.getString("sm.disable.msg") + "\n\n" : "";
         msg += bundle_session.getString("sm.disable.msg" + msgNo)
         var buttonPressed = promptService.confirmEx(win || window,
                        "TabMix " + bundle_session.getString("sm.title"),
                        msg,
                        (promptService.BUTTON_TITLE_YES * promptService.BUTTON_POS_0)
                        + (promptService.BUTTON_TITLE_NO * promptService.BUTTON_POS_1),
                        null, null, null, null, {});

         if ((msgNo == 1 && buttonPressed == 1) || ((msgNo == 2 && buttonPressed == 0)))
            gPref.setBoolPref("browser.sessionstore.enabled", false);
         else {
            gPref.setBoolPref("extensions.tabmix.sessions.manager", false);
            gPref.setBoolPref("extensions.tabmix.sessions.crashRecovery", false);
         }
      }

      delete window.setSession;
   },

   /**
    * @brief           remove closed tab from sessionStore list without restore
    *
    * @param aIndex    a Integer value - 0 or grater index to remove
    *                  other value empty the list.
    *
    * @returns         Nothing.
    */
   removeClosedTab: function TMP_ss_removeClosedTab(aIndex) {
      if (!gIsFirefox2 || !window.__SSi)
         return;

      var ss = Cc["@mozilla.org/browser/sessionstore;1"].
                  getService(Ci.nsISessionStore);

      var state = { windows: [], _firstTabs: true };
      state.windows[0] = { _closedTabs: [] };

      if (aIndex >= 0) {
         // get closed-tabs from nsSessionStore
         var closedTabs = eval("(" + ss.getClosedTabData(window) + ")");
         // purge closed tab at aIndex
         closedTabs.splice(aIndex, 1);
         state.windows[0]._closedTabs = closedTabs;
      }

      // replace existing _closedTabs
      ss.setWindowState(window, state.toSource(), false);
   },

   /**
    * @brief           get imange url from tab xultab data
    *
    * @param xultab    an object value - xultab from nsSessionStore
    *
    * @returns         image url or empty string.
    */
   getImage: function TMP_ss_getImage(xultab) {
      var image;
      if (xultab) {
         xultab.split(" ").forEach(function(aAttr) {
           if (/^([^\s=]+)=(.*)/.test(aAttr) && RegExp.$1 == "image") {
             image = decodeURI(RegExp.$2);
           }
         });
      }
      return image || "";
   }
}

/* ::::::::::::::::::::::::::::::::::::::::::::::::::::: */

// get closed-tabs from nsSessionStore
function getClosedTabs() {
  var ssEnabled = true;
  try {
    ssEnabled = gPref.getBoolPref("browser.sessionstore.enabled");
  } catch (ex) {}
  if (!ssEnabled)
    return;

  var ss = Cc["@mozilla.org/browser/sessionstore;1"].
           getService(Ci.nsISessionStore);

  if (ss.getClosedTabCount(window) == 0)
    return;

  var undoItems = eval("(" + ss.getClosedTabData(window) + ")");
  var tab, tabData;
  for (var i = undoItems.length - 1; i >= 0 ; i--) {
    tab = undoItems[i];
    tabData = tab.state;

    var history = Components.classes["@mozilla.org/browser/shistory;1"]
                                 .createInstance(tmSHistory);
    history = history.QueryInterface(Components.interfaces.nsISHistoryInternal);
    var aIdMap = { used: {} };

    for (var j in tabData.entries)
      history.addEntry(TMP_deserializeHistoryEntry(tabData.entries[j], aIdMap), true);

    // set history index
    var activeIndex = (tabData.index || tabData.entries.length) - 1;
    var _blank =  history.getEntryAtIndex(activeIndex, true);

    var scrollPos = (tabData.entries[activeIndex].scroll || "0,0").split(",");
    scrollPos = [parseInt(scrollPos[0]) || 0, parseInt(scrollPos[1]) || 0];

    gBrowser.closedTabs.push([tab.pos,
                               history,
                               tab.title,
                               TMP_SessionStore.getImage(tabData.xultab),
                               "0011111",
                               scrollPos[0] + "," + scrollPos[1] + "," + parseFloat(tabData.zoom || 1)
                              ]);
   if (gBrowser.closedTabs.length > tabxPrefs.getIntPref("undoCloseCache"))
      gBrowser.closedTabs.shift();
  }
  if (gBrowser.closedTabs.length > 0 && document.getElementById("btn_undoclose"))
    document.getElementById("btn_undoclose").setAttribute("disabled", "false");
}

  function TMP_deserializeHistoryEntry(aEntry, aIdMap) {
    var shEntry = Cc["@mozilla.org/browser/session-history-entry;1"].
                  createInstance(Ci.nsISHEntry);

    var ioService = Cc["@mozilla.org/network/io-service;1"].
                    getService(Ci.nsIIOService);
    shEntry.setURI(ioService.newURI(aEntry.url, null, null));
    shEntry.setTitle(aEntry.title || aEntry.url);
    shEntry.setIsSubFrame(aEntry.subframe || false);
    shEntry.loadType = Ci.nsIDocShellLoadInfo.loadHistory;

    if (aEntry.cacheKey) {
      var cacheKey = Cc["@mozilla.org/supports-PRUint32;1"].
                     createInstance(Ci.nsISupportsPRUint32);
      cacheKey.data = aEntry.cacheKey;
      shEntry.cacheKey = cacheKey;
    }
    if (aEntry.ID) {
      // get a new unique ID for this frame (since the one from the last
      // start might already be in use)
      var id = aIdMap[aEntry.ID] || 0;
      if (!id) {
        for (id = Date.now(); aIdMap.used[id]; id++);
        aIdMap[aEntry.ID] = id;
        aIdMap.used[id] = true;
      }
      shEntry.ID = id;
    }

    var scrollPos = (aEntry.scroll || "0,0").split(",");
    scrollPos = [parseInt(scrollPos[0]) || 0, parseInt(scrollPos[1]) || 0];
    shEntry.setScrollPosition(scrollPos[0], scrollPos[1]);

    if (aEntry.postdata) {
      var stream = Cc["@mozilla.org/io/string-input-stream;1"].
                   createInstance(Ci.nsIStringInputStream);
      stream.setData(aEntry.postdata, -1);
      shEntry.postData = stream;
    }

    if (aEntry.children && shEntry instanceof Ci.nsISHContainer) {
      for (var i in aEntry.children) {
        shEntry.AddChild(TMP_deserializeHistoryEntry(aEntry.children[i], aIdMap), i);
      }
    }

    return shEntry;
  }
/* ::::::::::::::::::::::::::::::::::::::::::::::::::::: */

var TMP_ClosedTabs = {
   /**
    * check to see if nsISessionStore is initialized
    */
   get ssIsON() {
      return gIsFirefox2 && "__SSi" in window;
   },

   setButtonState: function ct_setButtonState(value) {
      var btn = document.getElementById("btn_undoclose");
      if (!btn)
         return;

      if (!value)
         btn.removeAttribute("disabled");
      else if (btn.getAttribute("disabled") != "true")
         btn.setAttribute("disabled", "true");
   },

   undoCloseTab: function ct_undoCloseTab() {
      if (this.ssIsON)
         undoCloseTab();
      else
         gBrowser.undoRemoveTab();
   }

}
